package com.yang.modules.common.deploy;

import com.netflix.discovery.DiscoveryClient;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.yang.common.core.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * @author Billyang
 * @date 2024/9/18 14:34
 */
@Slf4j
@Component
public class RefreshHandler {

    /**
     * 刷新
     */
    public void refresh() {
        this.refreshRegistry();
        this.refreshRibbon();
    }

    /**
     * 刷新注册列表
     */
    private void refreshRegistry(){
        try{
            // 从Eureka Server获取注册信息，默认true
            boolean fetchRegistry = SpringContextUtil.getBooleanProperty("eureka.client.fetch-registry", true);
            if(!fetchRegistry){
                // 不获取注册信息，不需要刷新
                return;
            }

            //获取springCloud的注册刷新方法，然后手动刷新
            Method method = DiscoveryClient.class.getDeclaredMethod("refreshRegistry");
            method.setAccessible(true);
            method.invoke(SpringContextUtil.getBean(DiscoveryClient.class));
            log.info("refresh registry success!!!");
        }catch (Exception e){
            log.error("refresh registry fail!!!", e);
        }
    }

    /**
     * 刷新Ribbon列表
     */
    private void refreshRibbon(){
        try{
            SpringClientFactory springClientFactory = SpringContextUtil.getBean("springClientFactory");
            Method getContext = SpringClientFactory.class.getDeclaredMethod("getContext", String.class);
            getContext.setAccessible(true);
            Set<String> contextNames = springClientFactory.getContextNames();
            log.info("refreshRibbon contextNames:{}", contextNames);

            for(String contextName : contextNames){
                //更新每个服务对应的ribbon负载均衡器
                AnnotationConfigApplicationContext context = (AnnotationConfigApplicationContext) getContext
                        .invoke(springClientFactory, contextName);
                Object ribbonLoadBalancer = context.getBean("ribbonLoadBalancer");
                Method updateListOfServers = DynamicServerListLoadBalancer.class
                        .getDeclaredMethod("updateListOfServers");
                updateListOfServers.setAccessible(true);
                updateListOfServers.invoke(ribbonLoadBalancer);

//                Method getServerListImpl = DynamicServerListLoadBalancer.class
//                        .getDeclaredMethod("getServerListImpl");
//                getServerListImpl.setAccessible(true);
//                Object serverList = getServerListImpl.invoke(ribbonLoadBalancer);
//                log.info("after update ,{} serverList:{}", contextName, JSON.toJSONString(serverList));

                log.info("{} refresh success!!!", contextName);
            }
            log.info("refresh ribbon success!!!");
        }catch (Exception e){
            log.error("refresh ribbon fail!!!", e);
        }

    }
}
